﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace FRL.DebtChased.Silverlight.Library
{

	/// <summary>
	/// Declaration of ExtensionsForSilverlight class
	/// </summary>
	public static class ExtensionsForSilverlight
	{

		/////////////////////////////////////////////////////////////////
		// Create Debt Chased Endpoint

		public static double GetTrueHeight(this FrameworkElement el)
		{

			// Get height of panel
			double dblFtmp = el.ActualHeight;
			if (double.IsNaN(dblFtmp))
				dblFtmp = el.Height;
			return dblFtmp;

		}

		/////////////////////////////////////////////////////////////////
		// Create Debt Chased Endpoint

		public static System.ServiceModel.EndpointAddress CreateDebtChasedEndpoint()
		{

			// Declare return variable
			System.ServiceModel.EndpointAddress Ftmp = null;

			// Compose endpoint
#if DEBUG
			Ftmp = new System.ServiceModel.EndpointAddress(
				string.Format("http://localhost:{0}/WebServices/RichContentService.svc",
					3603
				)
			);
#else
			Ftmp = new System.ServiceModel.EndpointAddress(
				string.Format(
					"http://devsvr.computerc.co.uk/debtchased/WebServices/RichContentService.svc"
				)
			);
#endif // #if DEBUG

			// Return variable
			return Ftmp;

		}

		/////////////////////////////////////////////////////////////////
		// Extension - Find parent control

		public static FrameworkElement FindParent(this FrameworkElement el, Type type)
		{

			// Declare return variable
			FrameworkElement Ftmp = el;
			while (Ftmp != null)
			{

				// Move on
				Ftmp = Ftmp.Parent as FrameworkElement;
				if (Ftmp == null)
					break;

				// Compare types
				if (Ftmp.GetType() == type)
					break;

			}

			// Return variable
			return Ftmp;

		}
						
		public static DependencyObject FindParentByVisualTree(this DependencyObject el, Type type)
		{

			// Declare return variable
			DependencyObject Ftmp = el;
			while (Ftmp != null)
			{

				// Move on
				Ftmp = VisualTreeHelper.GetParent(Ftmp);
				if (Ftmp == null)
					break;

				// Compare types
				if (Ftmp.GetType() == type)
					break;

			}

			// Return variable
			return Ftmp;

		}

		/////////////////////////////////////////////////////////////////
		// Extension - Get child using Visual Tree

		public static FrameworkElement FindChildByVisualTree(this FrameworkElement el, Type type)
		{

			// shortcuts
			if (el == null)
				return null;
			if (el.GetType() == type)
				return el;

			// Declare return variable
			FrameworkElement Ftmp = null;

			// Loop through children
			for (int i1 = 0; i1 < VisualTreeHelper.GetChildrenCount(el); i1++)
			{

				// Get next child
				FrameworkElement child = VisualTreeHelper.GetChild(el, i1) as FrameworkElement;
				Ftmp = child.FindChildByVisualTree(type);
				if(Ftmp!=null)
					break;

			}

			// Return variable
			return Ftmp;
			
		}

		/////////////////////////////////////////////////////////////////
		// Extension - Get color from integer

		public static Color ToColor(this int i1)
		{
			
			// Convert to color
			return Color.FromArgb(
				(byte)0xFF,
				(byte)((i1 >> 24) & 0xFF),
				(byte)((i1 >> 16) & 0xFF),
				(byte)(i1 & 0xFF)
			);

		}

		/////////////////////////////////////////////////////////////
		// Static entension functions for controls

		public static void SelectValue(this ComboBox ctrl, int iSelectedValue)
		{

			// Loop through combo items
			foreach (object ob in ctrl.Items)
			{

				// Check interger value
				int iValue = Convert.ToInt32(ob);
				if (iValue == iSelectedValue)
				{
					ctrl.SelectedItem = ob;
					break;
				}
				
			}

		}

		public static void SelectByText(this ComboBox ctrl, string strValue, string strDefaultText)
		{

			// If no value, search for default
			if(string.IsNullOrEmpty(strValue))
				strValue = strDefaultText;

			// Loop through combo items
#if DEBUG
			bool bFound = false;
#endif // #if DEBUG
			for (int i1 = 0; i1 < ctrl.Items.Count; i1++)
			{

				// Compare items
				if (string.Compare(ctrl.Items[i1].ToString(), strValue, StringComparison.CurrentCulture) == 0)
				{

					// Update flag
#if DEBUG
					bFound = true;
#endif // #if DEBUG

					// Select item and break out of loop
					ctrl.SelectedIndex = i1;
					break;

				}

			}

			// Check item was found
#if DEBUG
			Debug.Assert(bFound);
#endif // #if DEBUG

		}

		public static void AddRows(this Grid grid, params int[] iRowHeights)
		{

			// Loop through the row heights
			foreach (int iRowHeight in iRowHeights)
			{

				// Create a grid length for the height
				GridLength height;
				if (iRowHeight == -1)
					height = new GridLength(1, GridUnitType.Star);
				else
					height = new GridLength(iRowHeight, GridUnitType.Pixel);

				// Create a new row definition
				RowDefinition newRow = new RowDefinition();
				newRow.Height = height;

				// Add to grid
				grid.RowDefinitions.Add(newRow);

			} // loop

		}

		public static void ShiftRowsDown(this Grid grid, int iMinRowIndex, int iCount)
		{

			// Loop through controls
			foreach (FrameworkElement el in grid.Children)
			{

				// Ignore non-framework elements
				if (el == null)
					continue;

				// If row matches...
				int iRowIndex = Grid.GetRow(el);
				if (iRowIndex >= iMinRowIndex)
				{

					// Shift down
					Grid.SetRow(el, iRowIndex + iCount);

				}

			}

		}

		public static void DeleteRows(this Grid grid, int iRowIndex, int iCount)
		{

			// Find all controls within these rows
			List<FrameworkElement> elementsToGo = new List<FrameworkElement>();
			foreach (FrameworkElement el in grid.Children)
			{

				// Ignore non-framework elements
				if (el == null)
					continue;

				// If row matches...
				int iElementRowIndex = Grid.GetRow(el);
				if (
					(iElementRowIndex >= iRowIndex)
					&&
					(iElementRowIndex < (iRowIndex + iCount))
				)
					elementsToGo.Add(el);

			}

			// Remove elements
			foreach (FrameworkElement el in elementsToGo)
				grid.Children.Remove(el);

			// Remove the rows
			for (int i1 = 0; i1 < iCount; i1++)
				grid.RowDefinitions.RemoveAt(iRowIndex);

			// Shift existing controls up
			ShiftRowsDown(grid, iRowIndex, -1 * iCount);

		}

		public static FrameworkElement FindCellContent(this Grid grid, int iColumn, int iRow, Type type)
		{

			// Declare return variable
			FrameworkElement Ftmp = null;

			// Find all controls within these rows
			foreach (FrameworkElement el in grid.Children)
			{

				// If cell and type matches...
				if (
					(Grid.GetColumn(el) == iColumn)
					&&
					(Grid.GetRow(el) == iRow)
					&&
					(el.GetType() == type)
				)
				{
					Ftmp = el;
					break;
				}

			}

			// Return variable
			return Ftmp;

		}

		public static double CalcDistance(this Point pt1, Point pt2)
		{

			// Return distance between points
			return Math.Sqrt(
				Math.Pow(pt1.X - pt2.X, 2)
				+
				Math.Pow(pt1.Y - pt2.Y, 2)
			);

		}

		public static int GetSelectedItemData(this ComboBox ctrl)
		{

			// Declare return variable
			int iFtmp = 0;

			// If an item is selected...
			object ob = ctrl.SelectedItem;
			if ((ob != null) && (ob is ComboBoxObject))
				iFtmp = (ob as ComboBoxObject).ItemData;
#if DEBUG
			else
				Debug.Assert(false);
#endif // #if DEBUG

			// Return variable
			return iFtmp;

		}

		public static string GetEnumDescription(Type enumType, int iValueIn)
		{

			// Declare return variable
			string strFtmp = null;

			// Get the type fields
			FieldInfo[] fi = enumType.GetFields();
			for (int i1 = 0; i1 < fi.Length; i1++)
			{

				// Ignore non-literals
				if ((fi[i1].Attributes & FieldAttributes.Literal) == 0)
					continue;

				// Get the value
				int iValue = (int)fi[i1].GetValue(enumType);
				if (iValue == iValueIn)
				{

					// Update return variable					
					DescriptionAttribute attr = Attribute.GetCustomAttribute(fi[i1], typeof(DescriptionAttribute)) as DescriptionAttribute;
					if (attr != null)
						strFtmp = attr.Description;
					else
						strFtmp = fi[i1].Name;

					// Break out of loop
					break;

				}

			}
#if DEBUG
			Debug.Assert(strFtmp != null);
#endif // #if DEBUG

			// Return variable
			return strFtmp;

		}

	}

}
